package com.touch.app.service.impl;

import com.alibaba.fastjson.JSON;
import com.touch.app.common.domain.*;
import com.touch.app.common.util.HttpUtils;
import com.touch.app.service.RequestServerService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@Slf4j
@Service
public class RequestServerServiceImpl implements RequestServerService {

    @Value("${openai.token}")
    private String TOKEN;

    @Value("${proxy.ip}")
    private String PROXY_IP;

    @Value("${proxy.port}")
    private String PROXY_PORT;

    @Value("${proxy.url}")
    private String PROXY_URL;

    private static final String BR = "<br />";

    @Override
    public String ask(Ask ask) {
        String question = ask.getQuestion();
        if (question != null && StringUtils.hasLength(question.trim())) {
            log.info("用户提问信息：{}", question);
            ChatGPTMessage message = new ChatGPTMessage(question);
            List<ChatGPTMessage> messageList = new LinkedList<>();
            messageList.add(message);
            ChatGPTRequest chatGPTRequest = new ChatGPTRequest(messageList);
            ChatGPTResponse response =  defaultRequestServer(chatGPTRequest);
            /*
            String defaultStr = "{\n" +
                    "  \"id\": \"chatcmpl-123\",\n" +
                    "  \"object\": \"chat.completion\",\n" +
                    "  \"created\": 1677652288,\n" +
                    "  \"choices\": [{\n" +
                    "    \"index\": 0,\n" +
                    "    \"message\": {\n" +
                    "      \"role\": \"assistant\",\n" +
                    "      \"content\": \"\\n\\nHello there, how may I assist you today?\",\n" +
                    "    },\n" +
                    "    \"finish_reason\": \"stop\"\n" +
                    "  }],\n" +
                    "  \"usage\": {\n" +
                    "    \"prompt_tokens\": 9,\n" +
                    "    \"completion_tokens\": 12,\n" +
                    "    \"total_tokens\": 21\n" +
                    "  }\n" +
                    "}\n";
            response = JSON.parseObject(defaultStr, ChatGPTResponse.class);
             */
            return parseGPTResponse(response);
        }else {
            return null;
        }
    }

    @Override
    public ChatGPTResponse requestServer(ChatGPTRequest chatGPTRequest, HttpServletRequest request) {
        Enumeration<String> headerNames = request.getHeaderNames();
        Map<String, String> headers = new HashMap<>();
        if (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            if (StringUtils.hasLength(headerName)) {
                String headerValue = request.getHeader(headerName);
                headers.put(headerName, headerValue);
            }
        }
        return post(chatGPTRequest, headers);
    }

    private ChatGPTResponse defaultRequestServer(ChatGPTRequest chatGPTRequest) {
        Map<String, String> headers = new HashMap<>();
        return post(chatGPTRequest, headers);
    }

    private String parseGPTResponse(ChatGPTResponse response) {
        if (response != null) {
            StringBuilder sb = new StringBuilder();
            sb.append(BR);
            List<Choices> choicesList = response.getChoices();
            if (choicesList == null || choicesList.isEmpty()) {
                log.error("GPT返回信息错误，返回信息：{}", response);
                return null;
            }
            for (Choices choices : choicesList) {
                ChatGPTMessage message = choices.getMessage();
                String content = message.getContent();
                if (StringUtils.hasLength(content)) {
                    content = content.replaceAll("(\r\n|\n)", BR);
                    sb.append(content);
                }
            }
            String answer = sb.toString();
            log.info("AI回复信息：{}", answer);
            return answer;
        }
        log.error("GPT返回信息错误，无返回信息");
        return null;
    }

    private ChatGPTResponse post(ChatGPTRequest chatGPTRequest, Map<String, String> headers) {
        headers = checkHeader(headers);
        String url = "http://" + PROXY_IP + ":" + PROXY_PORT + PROXY_URL;
        String response = HttpUtils.post(url, headers, JSON.toJSONString(chatGPTRequest));
        ChatGPTResponse chatGPTResponse;
        try {
            chatGPTResponse = JSON.parseObject(response, ChatGPTResponse.class);
        }catch (Exception e) {
            String errorMessage = "JSON parse Http response error, response is: [ " + response + "] error message is [" + e.getMessage() + "]";
            log.error(errorMessage);
            chatGPTResponse = new ChatGPTResponse();
            chatGPTResponse.setId(TOKEN);
            chatGPTResponse.setModel(chatGPTRequest.getModel());
            chatGPTResponse.setCreated(new Date().getTime());
            Choices choices = new Choices();
            ChatGPTMessage message = new ChatGPTMessage();
            message.setContent(errorMessage);
            message.setRole("assistant");
            choices.setMessage(message);
            List<Choices> choicesList = new LinkedList<>();
            choicesList.add(choices);
            chatGPTResponse.setChoices(choicesList);
        }
        return chatGPTResponse;
    }

    private Map<String, String> checkHeader(Map<String, String> headers) {
        if (headers == null || headers.isEmpty()) {
            headers = new HashMap<>();
            headers.put("Content-Type", "application/json");
            headers.put("Authorization", "Bearer " + TOKEN);
        }else {
            String contentType = headers.get("Content-Type");
            String auth = headers.get("Authorization");
            if (StringUtils.hasLength(contentType)) {
                headers.put("Content-Type", "application/json");
            }
            if (StringUtils.hasLength(auth)) {
                headers.put("Authorization", "Bearer " + TOKEN);
            }
        }
        return headers;
    }
}
